# geometry.two_d.rectangle -- Module for rectangle geometry
#
# Copyright (c) 2000, V.Kelson and M.Bakker
#

import copy
import math

import geometry.xy
import base
import point
import circle

class Rectangle(base.Geometry2d):
	'''Class for (horizontal) Rectangle Geometry

	Python call: Rectangle(pt1,pt2). pt1 and pt2 are two opposing corners,
	the routine calculates lower left and upper right.

	Attributes:

	- ll: Point object for lower left corner
	- ur: Point object for upper right corner'''
	
	# Class that holds a rectangle
	def __init__(self,pt1,pt2,tol=0.0):
		'''Constructor

		Python call: Rectangle(pt1,pt2). pt1 and pt2 are two opposing corners'''
		self.ll = point.Point( min(pt1.x,pt2.x), min(pt1.y,pt2.y) )
		self.ur = point.Point( max(pt1.x,pt2.x), max(pt1.y,pt2.y) )
	def __repr__(self):
		return 'Rectangle(' + repr(self.ll) + ',' + repr(self.ur) + ')' 
	def __str__(self):
		return self.__repr__()
	def isOnBoundary(self,pt,tol=0.0):
		# Not quite sure if this works
		if tol:
			checkTol = tol
		else:
			checkTol = self.tol
		for e in self.edges():
			if e.isOn(pt):
				return 1
		# If we got here, not on any of the edges...
		return 0
	def isInWidth(self,pt):
		return 0
	def isInArea(self,pt):
		return self.ll.x <= pt.x <= self.ur.x and \
		       self.ll.y <= pt.y <= self.ur.y
	def circumCircle(self):
		return circle.Circle( 0.5*(self.ll.x+self.ur.x),
			       0.5*(self.ll.y+self.ur.y),
			       0.5*math.sqrt(self.ll.distance2(self.ur)) )
	def map(self,pt):
		# return map(lambda(z):z.map(pt),self.edges())
		raise 'Must be fixed'
	def distance2(self,pt):
		# return min(map(lambda(z):z.distance2(pt),self.edges())
		raise 'Must be fixed'
	def edges(self):
		'''Computes edges of rectangle

		Returns the edges that bound the rectangle as a list of lines'''
		return [ Line(self.ll,XY(self.ll.x,self.ur.y)),
			 Line(XY(self.ll.x,self.ur.y),self.ur),
			 Line(self.ur,XY(self.ur.x,self.ll.y)),
			 Line(XY(self.ur.x,self.ur.y),self.ll) ]
	def overlaps(self,rect):
		'''Checks whether two rectangles overlap

		Returns TRUE if 'rect' overlaps the object'''
		if ( self.ll.x > rect.ur.x ) | \
		   ( self.ll.y > rect.ur.y ) | \
		   ( self.ur.x < rect.ll.x ) | \
		   ( self.ur.y < rect.ll.y ):
			return 0
		else:
			return 1
	def bbox(self,tol=0.0):
		space = geometry.XY(float(tol),float(tol))
		return Rectangle(self.ll-space,self.ur+space)
	def area(self):
		'''Computes area of rectangle

		Returns the area of the rectangle as a float'''
		return (self.ur.x-self.ll.x) * (self.ur.y-self.ll.y)
	def perimeter(self):
		'''Computes perimeter

		Returns the length of the perimeter as a float'''		
		return 2*(self.ur.x-self.ll.x) + 2*(self.ur.y-self.ll.y)
	def diagonal(self):
		'''Computes the diagonal

		Returns the diagonal of the rectangle as a float'''
		return math.sqrt(self.ur.distance2(self.ll))
